package com.jaks.xpense;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.text.InputFilter;
import android.text.Spanned;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.jaks.xpense.adapters.TileAdapter;
import com.jaks.xpense.data.Expenses;
import com.jaks.xpense.data.XpenseDatabase;
import com.jaks.xpense.data.entities.Tile;
import com.jaks.xpense.utils.Globals;

public class XpenseDroidActivity extends ListActivity implements OnClickListener {

	private Expenses expenses;
	private ArrayList<Tile> tiles;
	private String[] months;

	private final int TodayTileId = 1;
	private final int MonthlyTileId = 2;

	private final String grayColor = "#353535";
	private final String redColor = "#c03109";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home);

		expenses = new Expenses(this);
		months = getResources().getStringArray(R.array.monthsArray);
		tiles = new ArrayList<Tile>();

		View addExpense = findViewById(R.id.addExpenseTile);
		View search = findViewById(R.id.searchExpensesTile);
		addExpense.setOnClickListener(this);
		search.setOnClickListener(this);
	}

	private void populate() {

		String today = Globals.toDateText(Calendar.getInstance());
		double amount = expenses.getTotalAmount(today, today);
		int month = Calendar.getInstance().get(Calendar.MONTH);
		double balance = expenses.getBalance();
		String balanceColor = grayColor;
		if (balance < 0)
			balanceColor = redColor;

		tiles.clear();
		tiles.add(new Tile(TodayTileId, Globals.toDecimalText(amount), getString(R.string.today),
		    grayColor));
		tiles.add(new Tile(MonthlyTileId, Globals.toDecimalText(getCurrentMonthTotal()),
		    getString(R.string.thisText) + " " + months[month], grayColor));
		tiles
		    .add(new Tile(0, Globals.toDecimalText(balance), getString(R.string.balance), balanceColor));

		ArrayAdapter<Tile> adapter = new TileAdapter(this, R.layout.tile_info_row, R.id.infoCaption,
		    R.id.infoDesc, tiles);
		setListAdapter(adapter);
	}

	private double getCurrentWeekTotal() {

		Calendar from = Calendar.getInstance();
		from.add(Calendar.DATE, Calendar.SUNDAY - from.get(Calendar.DAY_OF_WEEK));

		Calendar to = Calendar.getInstance();
		to.add(Calendar.DATE, Calendar.SATURDAY - from.get(Calendar.DAY_OF_WEEK));

		return expenses.getTotalAmount(Globals.toDateText(from), Globals.toDateText(to));
	}

	private String[] getCurrentMonthDates() {
		Calendar from = Calendar.getInstance();
		from.set(Calendar.DATE, 1);

		Calendar to = Calendar.getInstance();
		to.set(Calendar.DATE, 1);
		to.add(Calendar.MONTH, 1);
		to.add(Calendar.DATE, -1);

		return new String[] { Globals.toDateText(from), Globals.toDateText(to) };
	}

	private double getCurrentMonthTotal() {

		String[] dates = getCurrentMonthDates();
		return expenses.getTotalAmount(dates[0], dates[1]);
	}

	private void manageTags() {
		Intent intent = new Intent(this, ManageTagsActivity.class);
		startActivity(intent);
	}

	private void manageIncomes() {
		Intent intent = new Intent(this, FilterIncomesActivity.class);
		startActivity(intent);
	}

	private void addExpense() {
		Intent intent = new Intent(this, EditExpenseActivity.class);
		startActivity(intent);
	}

	private void search() {
		Intent intent = new Intent(this, SearchCriteriaActivity.class);
		startActivity(intent);
	}

	private void filterExpenses(String from, String to) {
		String[] dates = new String[] { from, to };

		Intent intent = new Intent(this, FilterExpensesActivity.class);
		intent.putExtra("dates", dates);
		startActivityForResult(intent, 0);
	}

	private void restoreDatabase() {
		Intent intent = new Intent(this, RestoreDatabaseActivity.class);
		startActivity(intent);
	}

	private void showAbout() {
		AboutDialog about = new AboutDialog(this);
		about.setTitle(R.string.app_name);
		about.show();
	}

	private void showBackupDialog() {

		AlertDialog.Builder inputDialog = new AlertDialog.Builder(this);

		inputDialog.setTitle("Backup Xpense Database");
		inputDialog.setMessage("Filename");

		final EditText fileName = new EditText(this);
		fileName.setFilters(new InputFilter[] { filter });
		inputDialog.setView(fileName);

		inputDialog.setPositiveButton("Backup", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				String dbName = fileName.getText().toString();

				if ((dbName == null) || (dbName.trim().length() == 0))
					return;

				if (!dbName.endsWith(".db"))
					dbName = dbName + ".db";

				backupDatabase(dbName);
			}
		});

		inputDialog.show();
	}

	private void backupDatabase(String dbName) {

		File sd = Environment.getExternalStorageDirectory();
		File sdPath = new File(sd, Globals.ExternalFolderName);
		if (!sdPath.exists()) {
			if (!sdPath.mkdir()) {
				Toast.makeText(this, "Unable to create folder in sd card", Toast.LENGTH_SHORT).show();
				return;
			}
		}

		File backingDbName = new File(sdPath.getAbsolutePath(), dbName);
		XpenseDatabase db = new XpenseDatabase(this);
		try {
			db.backupDatabase(backingDbName.getAbsolutePath());
		} catch (IOException e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
			return;
		}

		Toast.makeText(this, "Database backed up !", Toast.LENGTH_LONG).show();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);

		menu.add(Menu.NONE, R.string.tags, Menu.NONE, R.string.tags).setIcon(
		    android.R.drawable.ic_menu_edit);
		menu.add(Menu.NONE, R.string.incomes, Menu.NONE, R.string.incomes).setIcon(
		    android.R.drawable.ic_menu_edit);
		menu.add(Menu.NONE, R.string.backup, Menu.NONE, R.string.backup).setIcon(
		    android.R.drawable.stat_sys_upload);
		menu.add(Menu.NONE, R.string.restore, Menu.NONE, R.string.restore).setIcon(
		    android.R.drawable.stat_sys_download);
		menu.add(Menu.NONE, R.string.about, Menu.NONE, R.string.about).setIcon(
		    android.R.drawable.ic_menu_info_details);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {

		switch (item.getItemId()) {
			case R.string.tags:
				manageTags();
				return true;
			case R.string.incomes:
				manageIncomes();
				return true;
			case R.string.backup:
				showBackupDialog();
				return true;
			case R.string.restore:
				restoreDatabase();
				return true;
			case R.string.about:
				showAbout();
				return true;
		}

		return super.onMenuItemSelected(featureId, item);
	}

	@Override
	protected void onStart() {
		super.onStart();

		populate();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		tiles.clear();
		expenses.close();
	}

	@Override
	protected void onListItemClick(ListView listView, View view, int position, long id) {
		super.onListItemClick(listView, view, position, id);

		Tile tile = tiles.get(position);

		switch (tile.getId()) {
			case TodayTileId:
				String today = Globals.toDateText(Calendar.getInstance());
				filterExpenses(today, today);
				break;
			case MonthlyTileId:
				String[] dates = getCurrentMonthDates();
				filterExpenses(dates[0], dates[1]);
				break;
		}
	}

	private final InputFilter filter = new InputFilter() {

		@Override
		public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
		    int dend) {

			for (int index = start; index < end; index++) {
				if (!Character.isLetterOrDigit(source.charAt(index))) {
					return "";
				}
			}
			return null;
		}
	};

	@Override
	public void onClick(View v) {

		switch (v.getId()) {
			case R.id.addExpenseTile:
				addExpense();
				break;
			case R.id.searchExpensesTile:
				search();
				break;
		}
	}
}
